import json

import pika
import uuid
import eventlet
import datetime
from st2reactor.sensor.base import PollingSensor


DESERIALIZATION_FUNCTIONS = {
    'json': json.loads
}


class TicketTaskSensor(PollingSensor):

    def __init__(self, sensor_service, config=None, poll_interval=5):
        super(TicketTaskSensor, self).__init__(sensor_service=sensor_service, config=config,
                                              poll_interval=poll_interval)
        self.host = self._config['task_sensor_config']['host']
        self.username = self._config['task_sensor_config']['username']
        self.password = self._config['task_sensor_config']['password']

        queue_sensor_config = self._config['task_sensor_config']['rabbitmq_queue_sensor']

        self.queues = queue_sensor_config['queues']
        if not isinstance(self.queues, list):
            self.queues = [self.queues]

        self.deserialization_method = queue_sensor_config['deserialization_method']

        self.conn = None
        self.channel = None
        self._logger = self._sensor_service.get_logger(name=self.__class__.__name__)

    def setup(self):
        if self.username and self.password:
            credentials = pika.PlainCredentials(username=self.username, password=self.password)
            connection_params = pika.ConnectionParameters(host=self.host, credentials=credentials)
        else:
            connection_params = pika.ConnectionParameters(host=self.host)
        self._logger.info("ticket setup {} {} {} {}".format(self.host, self.username, self.host, self.queues))

        self.conn = pika.BlockingConnection(connection_params)
        self.channel = self.conn.channel()
        self.channel.basic_qos(prefetch_count=1)

        for queue in self.queues:
            self.channel.queue_declare(queue=queue, durable=True)

            def callback(ch, method, properties, body, queue_copy=queue):
                self._dispatch_trigger(ch, method, properties, body, queue_copy)

            self.channel.basic_consume(callback, queue=queue)

    def _dispatch_trigger(self, ch, method, properties, body, queue):
        body = self._deserialize_body(body)
        self._logger.info("TicketTaskSensor Recevied message for queue {} with body {}".format(queue, body))

        payload = body
        if not isinstance(payload, dict):
            return

        payload = body

        try:
            self.sensor_service.dispatch("ticket.ticket_task_finish", payload=payload)
        finally:
            self.channel.basic_ack(delivery_tag=method.delivery_tag)

    @staticmethod
    def _get_trace_tag(payload):
        time = datetime.datetime.utcnow().strftime("%y%m%d%H%M%S")
        return 'ticket-{}-{}'.format(str(payload.get('tid', None)).zfill(6), time)

    def _deserialize_body(self, body):
        if not self.deserialization_method:
            return body

        deserialization_func = DESERIALIZATION_FUNCTIONS[self.deserialization_method]

        try:
            body = deserialization_func(body)
        except Exception as err:
            self._logger.info("{} deserialization body {} error {}".format(self.__class__.__name__, body, err))
        return body

    def poll(self):
        self._logger.info("Starting to consume message from rabbitmq for {}".format(self.queues))
        gt = eventlet.spawn(self.channel.start_consuming)
        gt.wait()

    def cleanup(self):
        if self.conn:
            self.conn.close()

    def add_trigger(self, trigger):
        pass

    def update_trigger(self, trigger):
        pass

    def remove_trigger(self, trigger):
        pass
